package my.code.charpter13;

/**
 * 一元方程求解 方法1：公式求解 方法2：二分逼近法 方法3：牛顿迭代法
 * 
 * @author xuyuji
 *
 */
public class Main {

	private static double PRECISION = 0.000000001;

	private static int count = 0;

	public static void main(String[] args) {
		new Main().method1();
		new Main().method2();
	}

	/**
	 * f(x) = 2x^2 + 3.2x - 1.8
	 * 
	 * @param x
	 * @return
	 */
	private double Function(double x) {
		return 2 * x * x + 3.2 * x - 1.8;
	}

	/**
	 * 找到一个区间[a,b],f(x)是连续函数,f(a) < 0 ,f(b) >0,则区间中有零点,即有方程解
	 */
	public void method1() {
		count = 0;
		System.out.println(DichotomyEquation(-0.8, 8));
		System.out.println("DichotomyEquation " + count + " times.");
	}

	/**
	 * 二分逼近法
	 * @param a
	 * @param b
	 * @return
	 */
	public double DichotomyEquation(double a, double b) {
		double mid = (a + b) / 2.0;
		while ((b - a) > PRECISION) {
			count++;
			if (Function(a) * Function(mid) < 0.0) {
				b = mid;
			} else {
				a = mid;
			}
			mid = (a + b) / 2.0;
		}

		return mid;
	}

	public void method2() {
		count = 0;
		System.out.println(NewtonRaphson(8));
		System.out.println("NewtonRaphson " + count + " times.");
	}

	/**
	 * 牛顿迭代法
	 * @param x0
	 * @return
	 */
	double NewtonRaphson(double x0) {
		double x1 = x0 - Function(x0) / CalcDerivative(x0);
		while (Math.abs(x1 - x0) > PRECISION) {
			count++;
			x0 = x1;
			x1 = x0 - Function(x0) / CalcDerivative(x0);
		}
		return x1;
	}

	double CalcDerivative(double x) {
		return (Function(x + 0.000005) - Function(x - 0.000005)) / 0.00001;
	}
}
